package edu.hubu.talentmanagementsystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.CaseFormat;
import edu.hubu.talentmanagementsystem.mapper.DepartmentMapper;
import edu.hubu.talentmanagementsystem.mapper.context.MapperContext;
import edu.hubu.talentmanagementsystem.model.ext.CompanyRecruitment;
import edu.hubu.talentmanagementsystem.model.ext.Department;
import edu.hubu.talentmanagementsystem.service.IDepartmentService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import edu.hubu.talentmanagementsystem.common.EncodeOperation;
import edu.hubu.talentmanagementsystem.common.EncodeParam;

import java.util.*;

/**
 * @author moonlan
 * date 2021/3/2 下午8:45
 */
@SuppressWarnings(value = "unused")
@Service
@Transactional(rollbackFor = Exception.class)
public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Department> implements IDepartmentService {

    private final MapperContext context;

    public DepartmentServiceImpl(MapperContext context) {this.context = context;}

    @Override
    public boolean deleteById(Integer id) {
        return context.getDepartmentMapper().deleteById(id) > 0;
    }

    @Override
    @EncodeOperation
    public Optional<Department> insert(@EncodeParam Department record) {
        int insert = context.getDepartmentMapper().insert(record);
        if (insert > 0) {
            return Optional.of(context.getDepartmentMapper().selectById(record.primaryKeyValue()));
        }
        return Optional.empty();
    }

    @Override
    public Optional<Department> selectById(Integer id) {
        QueryWrapper<Department> wrapper = new QueryWrapper<>();
        LambdaQueryWrapper<Department> lambdaQueryWrapper = getColumnWrapper(wrapper.lambda()).eq(Department::getDepartmentId, id);
        return Optional.of(context.getDepartmentMapper().selectOne(lambdaQueryWrapper));
    }

    @Override
    public List<Department> selectAll(String order) {
        QueryWrapper<Department> wrapper = new QueryWrapper<>();
        if (!StringUtils.hasText(order)) {
            LambdaQueryWrapper<Department> select = getColumnWrapper(wrapper.lambda());
            return context.getDepartmentMapper().selectList(select);
        }
        wrapper.orderByAsc(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, order));
        LambdaQueryWrapper<Department> select = getColumnWrapper(wrapper.lambda());
        return context.getDepartmentMapper().selectList(select);
    }

    @Override
    public Page<Department> selectAllPaged( Integer currentPage,
             Integer pageSize, String order) {
        QueryWrapper<Department> wrapper = new QueryWrapper<>();
        Page<Department> page = new Page<>(currentPage, pageSize);
        if (!StringUtils.hasText(order)) {
            LambdaQueryWrapper<Department> select = getColumnWrapper(wrapper.lambda());
            return context.getDepartmentMapper().selectPage(page, select);
        }
        wrapper.orderByAsc(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, order));
        LambdaQueryWrapper<Department> select = getColumnWrapper(wrapper.lambda());
        return context.getDepartmentMapper().selectPage(page, select);
    }

    private LambdaQueryWrapper<Department> getColumnWrapper(LambdaQueryWrapper<Department> wrapper) {
        return wrapper.select(
                Department::getCompany
                    ,
                Department::getDepartmentId
                    ,
                Department::getDepartmentNum
                    ,
                Department::getDepartmentName
                    ,
                Department::getDepartmentStaffId
                    ,
                Department::getDepartmentPhoneNumber
                    ,
                Department::getDepartmentEmail
                    ,
                Department::getDepartmentScale
                    ,
                Department::getDepartmentDesc
                    ,
                Department::getDepartmentCompanyId
        );
    }

    @Override
    public Page<Department> selectLikePaged( Integer currentPage,
             Integer pageSize, Department record, String order) {
        Page<Department> page = new Page<>(currentPage, pageSize);
        QueryWrapper<Department> wrapper = new QueryWrapper<>();
        if (!StringUtils.hasText(order)) {
            return context.getDepartmentMapper().selectPage(page, getColumnWrapper(getQueryWrapper(wrapper, record)));
        }
        wrapper.orderByAsc(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, order));
        return context.getDepartmentMapper().selectPage(page, getColumnWrapper(getQueryWrapper(wrapper, record)));
    }

    private LambdaQueryWrapper<Department> getQueryWrapper(QueryWrapper<Department>wrapper, Department record) {
        LambdaQueryWrapper<Department> lambda = wrapper.lambda();
        if (record.getCompany() != null) {
            lambda = lambda.eq(Department::getCompany,record.getCompany());
        }
        if (record.getDepartmentId() != null) {
            lambda = lambda.eq(Department::getDepartmentId,record.getDepartmentId());
        }
        if (record.getDepartmentStaffId() != null) {
            lambda = lambda.eq(Department::getDepartmentStaffId,record.getDepartmentStaffId());
        }
        if (record.getDepartmentScale() != null) {
            lambda = lambda.eq(Department::getDepartmentScale,record.getDepartmentScale());
        }
        if (record.getDepartmentCompanyId() != null) {
            lambda = lambda.eq(Department::getDepartmentCompanyId,record.getDepartmentCompanyId());
        }
        if (record.getDepartmentNum() != null) {
            lambda = lambda.like(Department::getDepartmentNum,record.getDepartmentNum ());
        }
        if (record.getDepartmentName() != null) {
            lambda = lambda.like(Department::getDepartmentName,record.getDepartmentName ());
        }
        if (record.getDepartmentPhoneNumber() != null) {
            lambda = lambda.like(Department::getDepartmentPhoneNumber,record.getDepartmentPhoneNumber ());
        }
        if (record.getDepartmentEmail() != null) {
            lambda = lambda.like(Department::getDepartmentEmail,record.getDepartmentEmail ());
        }
        if (record.getDepartmentDesc() != null) {
            lambda = lambda.like(Department::getDepartmentDesc,record.getDepartmentDesc ());
        }
        return lambda;
    }

    public int count(Department record) {
        return context.getDepartmentMapper().selectCount(getQueryWrapper(new QueryWrapper<>(), record));
    }

    @Override
    @EncodeOperation
    public Optional<Department> updateById(Integer id, @EncodeParam Department record) {
        record.setDepartmentId(id);
        int update = context.getDepartmentMapper().updateById(record);
        if (update > 0) {
            QueryWrapper<Department> wrapper = new QueryWrapper<>();
            LambdaQueryWrapper<Department> lambdaQueryWrapper = getColumnWrapper(wrapper.lambda()).eq(Department::getDepartmentId, id);
            return Optional.of(context.getDepartmentMapper().selectOne(getColumnWrapper(lambdaQueryWrapper)));
        }

        return Optional.empty();
    }

    @Override
    public Map<String,Object> selectListByCompanyId(Integer currentPage, Integer pageSize, Integer companyId) {
        Page<Department> departmentPage = context.getDepartmentMapper().selectPage(new Page<>(currentPage, pageSize),
                new QueryWrapper<Department>().eq("department_company_id", companyId));
        List<Department> departments = departmentPage.getRecords();
        List<String> departmentDirectors = new ArrayList<>();
        List<Integer> departmentRecruitmentNumList = new ArrayList<>();
        for (Department department : departments) {
            departmentDirectors.add(context.getStaffMapper().selectById(department.getDepartmentStaffId()).getStaffName());
            departmentRecruitmentNumList.add(context.getCompanyRecruitmentMapper().selectCount(new QueryWrapper<CompanyRecruitment>().eq("company_recruitment_company_id",department.getDepartmentCompanyId())));
        }
        Map<String,Object> result = new HashMap<>();
        result.put("departments",departments);
        result.put("currentPage",departmentPage.getCurrent());
        result.put("pageSize",departmentPage.getSize());
        result.put("total",departmentPage.getTotal());
        result.put("departmentDirectors",departmentDirectors);
        result.put("departmentRecruitmentNumList",departmentRecruitmentNumList);
        return result;
    }
}
